#pragma once
#include "UIAnimation.h"
#include "UIFromToByAnimation.h"
#include "UIRuntimeObject.h"
#include "UIButton.h"
#include "UIPage.h"
#include "UIRectangle.h"
#include "UIImage.h"
#include "UIGrid.h"

namespace DirectUI
{
	class CUIObjectFactory 
		: public CUINoAggregateObjectImplHelper<IUIObjectFactory, CUIObjectFactory, IUIObjectFactory>
	{
		DECLARE_CLASS(CUIObjectFactory, ObjectFactory)
	public:

		CUIObjectFactory()
		{
#define REGISTER_OBJECT_CLASS(className)	\
	RegisterObject((wchar_t*)className::ClassName(), className::ObjectType(), className::CreateObject);

			REGISTER_OBJECT_CLASS(CUIPage);
			REGISTER_OBJECT_CLASS(CUIImage);
			REGISTER_OBJECT_CLASS(CUIGrid);
			REGISTER_OBJECT_CLASS(CUIButton);
			REGISTER_OBJECT_CLASS(CUIRectangle);
			REGISTER_OBJECT_CLASS(UIAnimation::CUIStoryboard);
			REGISTER_OBJECT_CLASS(CUIInt32Object);
			REGISTER_OBJECT_CLASS(CUIInt64Object);
			REGISTER_OBJECT_CLASS(CUIDoubleObject);
			REGISTER_OBJECT_CLASS(CUIStringObject);
			REGISTER_OBJECT_CLASS(CUIFloatObject);
			REGISTER_OBJECT_CLASS(CUIPointObject);
			REGISTER_OBJECT_CLASS(CUIRectObject);
			REGISTER_OBJECT_CLASS(CUIBoolObject);
			REGISTER_OBJECT_CLASS(UIAnimation::CUIDoubleAnimation)
			REGISTER_OBJECT_CLASS(UIAnimation::CUIColorAnimation)
		}

	public:
		struct UIObjectRegisterInfo
		{
			UIObjectRegisterInfo()
			{
				lpName		= NULL;
				objectType	= ot_unknow;
				lpCreateFunc = NULL;
			}
			wchar_t*			lpName;
			UIObjectType		objectType;
			PFUNC_CreateObject	lpCreateFunc;
		};

		virtual bool RegisterObject(wchar_t* lpObjectName, UIObjectType objectType, PFUNC_CreateObject	lpCreateFunc)
		{
			if ( (lpObjectName == NULL && (objectType <= ot_unknow || objectType >= ot_Max))
				|| lpCreateFunc == NULL )
			{
				assert(false);
				return false;
			}

			UIObjectRegisterInfo ri;
			ri.lpName = lpObjectName;
			ri.objectType = objectType;
			ri.lpCreateFunc = lpCreateFunc;
			if ( ri.lpName )
			{
				CString szName = ri.lpName;
				szName.Trim(), szName.MakeLower();
				std::map<CString, UIObjectRegisterInfo>::iterator pit = m_mapNameObjectRegisterInfos.find(szName);
				if ( pit != m_mapNameObjectRegisterInfos.end() )
				{
					assert(false);
					return false;
				}
				m_mapNameObjectRegisterInfos[szName] = ri;
			}
			
			if ( objectType > ot_unknow || objectType < ot_Max )
			{
				std::map<UIObjectType, UIObjectRegisterInfo>::iterator pit = m_mapObjectTypeObjectRegisterInfos.find(objectType);
				if ( pit != m_mapObjectTypeObjectRegisterInfos.end() )
				{
					assert(false);
					return false;
				}
				m_mapObjectTypeObjectRegisterInfos[objectType] = ri;
				return true;
			}
			return true;
		}

		virtual bool CreateObject(wchar_t* lpTypeName, UIObjectType ObjectType, IUIObject** lppObj)
		{
			CString szName = lpTypeName;
			szName.Trim(), szName.MakeLower();
			if ( !szName.IsEmpty() )
			{
				std::map<CString, UIObjectRegisterInfo>::iterator pit = m_mapNameObjectRegisterInfos.find(szName);
				if ( pit != m_mapNameObjectRegisterInfos.end() )
				{
					IUIObject* p = pit->second.lpCreateFunc();
					if ( p )
					{
						p->AddRef();
						*lppObj = p;
						return true;
					}
				}
			}

			std::map<UIObjectType, UIObjectRegisterInfo>::iterator pit = m_mapObjectTypeObjectRegisterInfos.find(ObjectType);
			if ( pit != m_mapObjectTypeObjectRegisterInfos.end() )
			{
				IUIObject* p = pit->second.lpCreateFunc();
				if ( p )
				{
					p->AddRef();
					*lppObj = p;
					return true;
				}
			}
			return false;
		}

	private:
		std::map<CString, UIObjectRegisterInfo>			m_mapNameObjectRegisterInfos;
		std::map<UIObjectType, UIObjectRegisterInfo>	m_mapObjectTypeObjectRegisterInfos;
	};
};

